package com.coocaa.typhoon.api.v1.userfile.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import com.coocaa.cirrus.common.base.util.DateUtil;
import com.coocaa.typhoon.api.third.volcengine.model.output.UserFileVO;
import com.coocaa.typhoon.api.third.volcengine.service.TOSService;
import com.coocaa.typhoon.api.third.volcengine.service.VikingDbUserFileService;
import com.coocaa.typhoon.api.third.volcengine.yml.VolcConfigYml;
import com.coocaa.typhoon.api.v1.userfile.constant.FileSceneConstant;
import com.coocaa.typhoon.api.v1.userfile.constant.UploadTypeConstant;
import com.coocaa.typhoon.api.v1.userfile.model.UploadTmpResult;
import com.coocaa.typhoon.api.v1.userfile.model.input.GetSearchDataModel;
import com.coocaa.typhoon.api.v1.userfile.model.input.GetTaskDataModel;
import com.coocaa.typhoon.api.v1.userfile.model.input.UploadDataModel;
import com.coocaa.typhoon.api.v1.userfile.model.output.RlsFileInfo;
import com.coocaa.typhoon.api.v1.userfile.model.output.SearchResultModel;
import com.coocaa.typhoon.api.v1.userfile.model.output.TaskProgressResultModel;
import com.coocaa.typhoon.api.v1.userfile.model.output.UploadResultModel;
import com.coocaa.typhoon.api.v1.userfile.provider.UserFileMgrProvider;
import com.coocaa.typhoon.api.v1.userfile.util.FileTypeCheckUtil;
import com.coocaa.typhoon.api.v1.userfile.util.TosFinalUrlUtil;
import com.volcengine.tos.comm.event.DataTransferType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author bijiahao
 * @date : 2025/9/18 10:02
 * @description
 */
@Slf4j
@Service
public class UserFileService {
    @Autowired
    private UserFileMgrProvider userFileProvider;
    @Autowired
    private VikingDbUserFileService vikingDbUserFileService;
    @Autowired
    private TOSService tosService;
    @Autowired
    private VolcConfigYml vikingDbYml;
    @Autowired
    private ThreadPoolTaskExecutor uploadThreadPoolExecutor;

    public List<UploadResultModel> uploadBatch(MultipartFile[] files, UploadDataModel dataModel) throws Exception {
        String userId = dataModel.getUserId();
        List<CompletableFuture<UploadResultModel>> futures = new ArrayList<>();
        for (MultipartFile file : files) {
            CompletableFuture<UploadResultModel> future = CompletableFuture.supplyAsync(() -> {
                return handleEach(file, userId, dataModel);
            }, uploadThreadPoolExecutor);
            futures.add(future);
        }
        // 等待所有任务完成，然后合并结果
        CompletableFuture<List<UploadResultModel>> allFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .thenApply(v -> futures.stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList()));
        List<UploadResultModel> res = allFuture.join();
        return res;
    }

    private UploadResultModel handleEach(MultipartFile file, String userId, UploadDataModel dataModel) {
        String taskId = IdUtil.randomUUID();
        UploadResultModel uploadResultModel = new UploadResultModel();
        uploadResultModel.setTaskId(taskId);
        // 上传
        UploadTmpResult uploadTmpResult = userFileProvider.upload(taskId, file, userId, dataModel);
        if (null == uploadTmpResult) {
            uploadResultModel.setUploadStatus(DataTransferType.DATA_TRANSFER_FAILED.toString());
            return uploadResultModel;
        }
        uploadResultModel.setUrl(uploadTmpResult.getUrl());
        uploadResultModel.setDuration(uploadTmpResult.getDuration());
        uploadResultModel.setUploadStatus(DataTransferType.DATA_TRANSFER_SUCCEED.toString());
        if (UploadTypeConstant.isSearchFile(dataModel.getUploadType())) {
            uploadResultModel.setTosLink(uploadTmpResult.getTosLink());
        }
        if (Objects.equals(1, dataModel.getOutType()) && FileTypeCheckUtil.isCanSplitImage(uploadTmpResult.getFileExtName())) {
            uploadResultModel.setRlsFileList(listRlsFile(uploadTmpResult.getTosLink()));
        }
        return uploadResultModel;
    }


    public List<TaskProgressResultModel> progress(GetTaskDataModel data) {
        return userFileProvider.progress(data);
    }


    public List<SearchResultModel> searchMultiModal(GetSearchDataModel dataModel) {
        Integer limitRecall = null == vikingDbYml.getLimitRecall() ? 50 : vikingDbYml.getLimitRecall();
        dataModel.setLimit(limitRecall);
        List<UserFileVO> userFileVOList = vikingDbUserFileService.searchWithMultiModal(dataModel);
        if (CollectionUtils.isEmpty(userFileVOList)) {
            return null;
        }
        if (null != vikingDbYml.getLimitScore()) {
            userFileVOList = userFileVOList.stream().filter(userFileVO -> userFileVO.getScore() > vikingDbYml.getLimitScore()).collect(Collectors.toList());
        }
        LinkedHashMap<String, SearchResultModel> tosLinkSearchResult = new LinkedHashMap<>();
        userFileVOList.forEach(userFileVO -> {
            handleEach(tosLinkSearchResult, userFileVO, dataModel);
        });
        List<SearchResultModel> res = new ArrayList<>();
        tosLinkSearchResult.forEach((key, value) -> {
            res.add(value);
        });
        return res;
    }

    private void handleEach(LinkedHashMap<String, SearchResultModel> tosLinkSearchResult, UserFileVO userFileVO, GetSearchDataModel dataModel) {
        if (!FileSceneConstant.isPreview(userFileVO.getTosLink())) {
            SearchResultModel searchResultModel = getSearchResultModel(userFileVO);
            tosLinkSearchResult.put(userFileVO.getTosLink(), searchResultModel);
            return;
        }
        if (FileTypeCheckUtil.isImageQuery(dataModel.getFileType())) {
            return;
        }
        //父文件的TOS链接
        String parentTosLink = TosFinalUrlUtil.getParentTosLink(userFileVO.getTosLink());
        //父文件路径
        String parentFilePath = TosFinalUrlUtil.getFilePath(parentTosLink);
        SearchResultModel searchResultModel = tosLinkSearchResult.get(parentTosLink);
        if (null == searchResultModel) {
            searchResultModel = new SearchResultModel();
            searchResultModel.setUserId(userFileVO.getUserId());
            searchResultModel.setFileUrl(tosService.getFinalUrl(parentFilePath));
            searchResultModel.setFileType(FileNameUtil.extName(parentFilePath).toUpperCase());
            searchResultModel.setUploadTimeStr(DateUtil.timestampToString(userFileVO.getUploadTime()));
            //关联的图片
            List<RlsFileInfo> rlsFileList = tosService.listRlsFileList(parentFilePath);
            //设置关联文件的信息
            setRlsFileInfo(rlsFileList, userFileVO);
            searchResultModel.setRlsFileList(rlsFileList);
            tosLinkSearchResult.put(parentTosLink, searchResultModel);
        } else {
            //设置关联文件的信息
            setRlsFileInfo(searchResultModel.getRlsFileList(), userFileVO);
        }
    }

    private List<RlsFileInfo> listRlsFile(String parentTosLink) {
        //父文件路径
        String parentFilePath = TosFinalUrlUtil.getFilePath(parentTosLink);
        //关联的图片
        List<RlsFileInfo> rlsFileList = tosService.listRlsFileList(parentFilePath);
        return rlsFileList;
    }


    /**
     * 设置关联文件的信息
     *
     * @param rlsFileList
     * @param userFileVO
     */
    private static void setRlsFileInfo(List<RlsFileInfo> rlsFileList, UserFileVO userFileVO) {
        //预览图片的文件路径
        String filePath = TosFinalUrlUtil.getFilePath(userFileVO.getTosLink());
        RlsFileInfo match = rlsFileList.stream().filter(rlsFileInfo -> Objects.equals(filePath, rlsFileInfo.getFilePath())).findFirst().orElse(null);
        if (null != match) {
            match.setScore(userFileVO.getScore());
        }
    }

    private SearchResultModel getSearchResultModel(UserFileVO userFileVO) {
        SearchResultModel res = new SearchResultModel();
        BeanUtil.copyProperties(userFileVO, res);
        //最终下发的地址
        String filePath = TosFinalUrlUtil.getFilePath(userFileVO.getTosLink());
        String fileUrl = tosService.getFinalUrl(filePath);
        res.setFileUrl(fileUrl);
        res.setShootTimeStr(DateUtil.timestampToString(userFileVO.getShootTime()));
        res.setUploadTimeStr(DateUtil.timestampToString(userFileVO.getUploadTime()));
        return res;
    }
}
